package com.liming.common.enums;

import com.liming.common.exception.BusinessException;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

/**
 * @author liming
 * @date 2025/6/20
 */
@Getter
@AllArgsConstructor
public enum ThreadPoolQueueEnum {

    /**
     * FixedThreadPool 和 SingleThreadExecutor 。
     * FixedThreadPool最多只能创建核心线程数的线程（核心线程数和最大线程数相等），
     * SingleThreadExecutor只能创建一个线程（核心线程数和最大线程数都是 1），二者的任务队列永远不会被放满。
     */
    LINKED_BLOCKING("LinkedBlockingQueue", "有界阻塞队列") {
        @Override
        public BlockingQueue<Runnable> createQueue() {
            return new LinkedBlockingQueue<>();
        }
    },
    /**
     * CachedThreadPool 。
     * SynchronousQueue 没有容量，不存储元素，目的是保证对于提交的任务，如果有空闲线程，则使用空闲线程来处理；否则新建一个线程来处理任务。
     * 也就是说，CachedThreadPool 的最大线程数是 Integer.MAX_VALUE ，可以理解为线程数是可以无限扩展的，可能会创建大量线程，从而导致 OOM。
     */
    SYNCHRONOUS("SynchronousQueue", "同步队列") {
        @Override
        public BlockingQueue<Runnable> createQueue() {
            return new SynchronousQueue<>();
        }
    },
    /**
     * ScheduledThreadPool 和 SingleThreadScheduledExecutor 。
     * DelayedWorkQueue 的内部元素并不是按照放入的时间排序，而是会按照延迟的时间长短对任务进行排序，
     * 内部采用的是“堆”的数据结构，可以保证每次出队的任务都是当前队列中执行时间最靠前的。
     * DelayedWorkQueue 添加元素满了之后会自动扩容，增加原来容量的 50%，即永远不会阻塞，最大扩容可达 Integer.MAX_VALUE，所以最多只能创建核心线程数的线程。
     */
    DELAYED_WORK("DelayedWorkQueue", "延迟队列") {
        @Override
        public BlockingQueue<Runnable> createQueue() {
//            Executors.newScheduledThreadPool(2);
            throw new BusinessException("无法new, 只能使用ScheduledThreadPool");
        }
    },
    /**
     * 底层由数组实现，容量一旦创建，就不能修改。
     */
    ARRAY_BLOCKING("ArrayBlockingQueue", "有界阻塞队列") {
        @Override
        public BlockingQueue<Runnable> createQueue() {
            return new ArrayBlockingQueue<>(100);
        }
    };


    private final String name;
    private final String desc;

    // 创建队列方法
    public abstract BlockingQueue<Runnable> createQueue();
}
